// win32-clipboard.cpp : This file contains the 'main' function. Program execution begins and ends there.
//


/*****************************************************************************
 *  cpaste.c
 *  Simple program to dump hex from Win32 clipboard to stdout
 *
 *  You'll have to link this to user32.lib (or libuser32.a with cygwin)
 *
 *  I've built this with MSVC++6 and EGCS 2.91.57
 *
 *  wharfinger  1/17/01
 *****************************************************************************/

#include <stdio.h>
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <objbase.h>

#include <tchar.h>
#include <iostream>
#include <vector>
#include "print-util.h"

void print_menu()
{
    std::cout << "L)ist formats\n";
    std::cout << "D)ump format\n";
    std::cout << "Q)uit format\n";
}
 /*  Get text from clipboard and copy into string.  Return size of string.  */
int cbtostr(char** s);

/*---------------------------------------------------------------------------*/
int main(int argc, char* argv[])
{
    /*  There aren't any arguments.  If the user tries to give us one, s/he's
     *  obviously disoriented and in need of help.  Sadly, we can't help.  We
     *  can't even help ourselves, much less some random user out there in the
     *  darkness.  All we can do is explain what this stupid program does.  So
     *  that's what we do.
     */ 
    void enum_formats(std::vector<UINT> &fmts);
    void print_formats(const std::vector<UINT> fmts);
    void dump_fmt(UINT fmt);

    std::vector<UINT> fmts;
    do
    {
        char c;
        print_menu();
        std::cin >> c;
        if (c == 'Q') break;
        if (c == 'L')
        {
            fmts.clear();
            enum_formats(fmts);
            print_formats(fmts);
        }
        if (c == 'D')
        {
            int i;
            std::cout << "format index (0-" <<fmts.size() << "):\n";
            std::cin >> i;
            if (i < fmts.size())
            {
                dump_fmt(fmts[i]);
            }
         
        }
    } while (1);
    

    return 1;
}

LPCTSTR GetPredefinedClipboardFormatName(UINT fmt);

/*---------------------------------------------------------------------------*/
void dump_fmt(UINT fmt)
{
    if(IsClipboardFormatAvailable(fmt))
        /*  If there's nothing there, we'd look mighty silly trying to get our
         *  grimly little hands on it, no?
         */
    {

        HGLOBAL glob;
        char* cbtext;
        size_t  size;

        OpenClipboard(NULL);  /*  Argument is HWND; we don't have one  */

        /*  CF_TEXT is an int constant which specifies that we're looking for
         *  text data -- or at least data that somebody *described* as text.
         *  It's no skin off my ass either way.  The clipboard can hold
         *  different data for each of an arbitrary number of different
         *  "formats", all at the same time.
         */
        glob = GetClipboardData(fmt);
        if (glob)
        {
            size = GlobalSize(glob);

            /*  We're given a "handle" to global memory containing the clipboard
             *  data.  We have to call GlobalLock() to get a pointer to the
             *  memory that the handle refers to.
             */
            cbtext = (char*)GlobalLock(glob);

            if (cbtext)
            {

                print_mem32(cbtext, 0, size);
            }
            GlobalUnlock(glob);
        }

        /*  This is good manners.  It'll get closed when our process exits
         *  anyway, and that'll be happening very, very soon -- but this is an
         *  example program, so we'll do the right thing.
         */
        CloseClipboard();


    }
}


/*****************************************************************************/
BOOL WINAPI IsDisplayableFormat(UINT uFormat)
{
    switch (uFormat)
    {
    case CF_OWNERDISPLAY:
    case CF_TEXT:
    case CF_ENHMETAFILE:
    case CF_BITMAP:
        return TRUE;
    }
    return FALSE;
}

void enum_formats(std::vector<UINT>& fmts)
{
    if (CountClipboardFormats() == 0)
        return;

    // Open the clipboard. 

    if (!OpenClipboard(NULL))
        return;

    UINT uFormat = EnumClipboardFormats(0);

    while (uFormat)
    {
        fmts.push_back(uFormat);
        uFormat = EnumClipboardFormats(uFormat);        
    }
    CloseClipboard();
}
void print_formats(const std::vector<UINT> fmts)
{
        TCHAR szFormatName[128];
        LPCTSTR lpFormatName;
        // Call an application-defined function to get the name 
        // of the clipboard format. 

        int i = 0;
        for (UINT uFormat : fmts)
        {
            // Call an application-defined function to get the name 
            // of the clipboard format. 

            lpFormatName = GetPredefinedClipboardFormatName(uFormat);
            // For registered formats, get the registered name. 

            if (lpFormatName == NULL)
            {
                // Note that, if the format name is larger than the
                // buffer, it is truncated. 
                if (GetClipboardFormatName(uFormat, szFormatName,
                    sizeof(szFormatName)))
                    lpFormatName = szFormatName;
                else
                    lpFormatName = _T("(unknown)");
            }


            // Add a menu item for the format. For displayable 
            // formats, use the format ID for the menu ID. 

           // (IsDisplayableFormat(uFormat))
            wprintf(_T("% 3d %04x-%s\n"), i,uFormat, lpFormatName);
            i++;
        }


}

#define FMT_SYM(x)  _T(#x),

const TCHAR* fmt_sym[] = {
FMT_SYM(CF_TEXT)
FMT_SYM(CF_BITMAP)
FMT_SYM(CF_METAFILEPICT)
FMT_SYM(CF_SYLK)
FMT_SYM(CF_DIF)
FMT_SYM(CF_TIFF)
FMT_SYM(CF_OEMTEXT)
FMT_SYM(CF_DIB)
FMT_SYM(CF_PALETTE)
FMT_SYM(CF_PENDATA)
FMT_SYM(CF_RIFF)
FMT_SYM(CF_WAVE)
FMT_SYM(CF_UNICODETEXT)
FMT_SYM(CF_ENHMETAFILE)
FMT_SYM(CF_HDROP)
FMT_SYM(CF_LOCALE)
FMT_SYM(CF_DIBV5)
};

LPCTSTR GetPredefinedClipboardFormatName(UINT fmt)
{
    return (fmt > 0 && fmt < CF_MAX) ? fmt_sym[fmt-1] : NULL;
}

/*****************************************************************************/